package com.iot08.admin.service;

import com.aliyun.tea.utils.StringUtils;
import com.iot08.admin.service.page.PageVO;
import com.iot08.admin.service.page.PageableImpl;
import com.iot08.common.entity.admin.SysUser;
import com.iot08.common.entity.app.BrokenScreenInsurance;
import com.iot08.common.entity.app.PxAdverster;
import com.iot08.common.response.Response;
import com.iot08.common.service.base.BaseService;
import com.iot08.common.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.bson.types.ObjectId;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author cwj
 * @description
 * @date 2025/4/15 15:14
 **/
@Slf4j
@Service
public class BrokenScreenInsuranceService extends BaseService<BrokenScreenInsurance> {

    @Resource
    private OperationService operationService;

    /**
     * @description 分页查询
     * @author cwj
     * @param [page]
     * @return org.springframework.data.domain.Page<com.iot08.common.entity.app.BrokenScreenInsurance>
     * @date @time 2025/4/15 15:23
     **/
    public Page<BrokenScreenInsurance> list(PageVO page,String openid,String checkCode,Integer status) {
        PageableImpl pageable = new PageableImpl();
        page.setSort(Sort.by(Sort.Order.desc("createTime")));
        pageable.setPage(page);
        Criteria criteria = new Criteria();
        if (StringUtil.isNotBlank(page.getSearchValue())) {
            criteria.and("_id").is(page.getSearchValue());
        }
        if(!StringUtils.isEmpty(openid)) {
            criteria.and("openid").is(openid);
        }
        if(!StringUtils.isEmpty(checkCode)) {
            criteria.and("checkCode").is(checkCode);
        }
        if(ObjectUtils.isNotEmpty(status)) {
            criteria.and("status").is(status);
        }
        Query query = new Query().addCriteria(criteria);
        long count = this.count(query);
        page.setTotalResult((int) count);
        List<BrokenScreenInsurance> list = this.find(query.with(pageable));
        Long currentTime = System.currentTimeMillis()/1000;
        //记录状态为生效中，实际上已经过期的碎屏险
        List<String> ids = new ArrayList<>();
        list.forEach(b->{
            if(Integer.valueOf(1).equals(b.getStatus()) && (currentTime>b.getEndTime())) {
                ids.add(b.getId());
                b.setStatus(3);
            }
        });
        Page<BrokenScreenInsurance> result = new PageImpl<BrokenScreenInsurance>(list, pageable, count);
        if(!CollectionUtils.isEmpty(ids)) {
            //更新碎屏险的状态
            updateStatusByStrIds(ids,3);
        }
        return result;
    }

    /**
     * @description 根据操作类型进行核销或撤销核销
     * @author cwj
     * @param [id, type]
     * @return void
     * @date @time 2025/4/15 17:54
     **/
    public Response<Object> cancelVerification(String id, Integer type, SysUser user, String ip){
        BrokenScreenInsurance brokenScreenInsurance = this.findById(new ObjectId(id));
        if(ObjectUtils.isEmpty(brokenScreenInsurance)) {
            log.error("id为：{}的碎屏险记录不存在！",id);
            return Response.failedResponse("您所选择的碎屏险记录不存在！");
        }
        Update update = new Update();
        update.set("updateTime",new Date());
        Long currentTime = System.currentTimeMillis()/1000;
        if(Integer.valueOf(0).equals(type)) {
            //有效中且还存在核销次数的数据
            if(brokenScreenInsurance.getNum()>0 && currentTime <= brokenScreenInsurance.getEndTime() && Integer.valueOf(1).equals(brokenScreenInsurance.getStatus())){
                update.set("num",brokenScreenInsurance.getNum()-1);
                update.set("useNum",brokenScreenInsurance.getUseNum()+1);
                if(brokenScreenInsurance.getNum()-1 <= 0) {
                    update.set("status",2);
                }
                this.updateById(new ObjectId(id),update);
                operationService.add(user, ip, "核销碎屏险", "编辑",
                        String.format("核销碎屏险: %s ", brokenScreenInsurance.getCheckCode()));
            } else {
                log.error("id为：{}的碎屏险记录已用完、已过期或已失效",id);
                return Response.failedResponse("碎屏险记录已用完、已过期或已失效！");
            }
        } else {
            //没过期、没失效且已经核销过的数据才能撤销核销
            if(brokenScreenInsurance.getUseNum()>0 && currentTime <= brokenScreenInsurance.getEndTime() &&
                    (Integer.valueOf(1).equals(brokenScreenInsurance.getStatus()) || Integer.valueOf(2).equals(brokenScreenInsurance.getStatus()))){
                update.set("num",brokenScreenInsurance.getNum()+1);
                update.set("useNum",brokenScreenInsurance.getUseNum()-1);
                if(brokenScreenInsurance.getNum()+1 > 0) {
                    update.set("status",1);
                }
                this.updateById(new ObjectId(id),update);
                operationService.add(user, ip, "撤销核销碎屏险", "编辑",
                        String.format("撤销核销碎屏险: %s ", brokenScreenInsurance.getCheckCode()));
            } else {
                log.error("id为：{}的碎屏险记录已过期或已失效",id);
                return Response.failedResponse("碎屏险记录已过期或已失效！");
            }
        }
        return Response.successResponse();
    }

    /**
     * @description 根据id集合更新状态
     * @author cwj
     * @param [ids, status]
     * @return void
     * @date @time 2025/4/15 16:21
     **/
    public void updateStatusByIds(List<ObjectId> ids, Integer status) {
        Query query = new Query(Criteria.where("_id").in(ids));
        Update update = new Update().set("status", status);
        mongoTemplate.updateMulti(query, update, getTClass());
    }

    /**
     * @description 根据id集合更新状态
     * @author cwj
     * @param [ids, status]
     * @return void
     * @date @time 2025/4/15 16:23
     **/
    public void updateStatusByStrIds(List<String> ids, Integer status) {
        Query query = new Query(Criteria.where("_id").in(ids.stream().map(ObjectId::new).collect(Collectors.toList())));
        Update update = new Update().set("status", status);
        mongoTemplate.updateMulti(query, update, getTClass());
    }
}
